package cn.cocho.android.mc.comp.button;

import java.util.HashSet;
import java.util.Set;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewParent;
import android.widget.TextView;

import cn.cocho.android.mc.R;

public class McToggleButton extends TextView {
	private static final String T_BG = "toggled_backgournd";
	private static final String T_BG_P = "toggled_backgournd_pressed";
	private static final String N_BG_P = "noremal_backgournd_pressed";
	private static final String BG_VIEW_ID = "bg_view_id";
	private static final String[] T_ICONS = { "toggled_icon_left", "toggled_icon_top", "toggled_icon_right", "toggled_icon_bottom" };
	private static final String T_COLOR = "toggled_text_color";
	private static final String AS_N_BTN = "work_as_normal_button";
	private boolean toggled = false;
	private boolean workAsNormal = false;
	private Drawable normalBg;
	private Drawable normalBgPressed;
	private Drawable[] normalIcons;
	private int normalTextColor;
	private Drawable toggledBg;
	private Drawable toggledBgPressed;
	private Drawable[] toggledIcons;
	private int toggledTextColor;
	private View bgView;
	private int bgViewId;

	private OnClickListener listener;
	private ButtonGroup buttonGroup;

	public McToggleButton(Context context) {
		super(context);
		bgView = this;
	}
	
	public McToggleButton(Context context, AttributeSet attrs, int defstyle){
		super(context, attrs, defstyle);
	}

//	public TbcToggleButton(Context context, AttributeSet attrs) {
//		super(context, attrs);
//		initTargetBgView(context, attrs);
//		initToggledTextColor(context, attrs);
//		initBackgroundAndIcons(context, attrs);
//		initWorkAsNormalBtn(context, attrs);
//	}

	//*↑
	public McToggleButton(Context context, AttributeSet attrs) {
		super(context, attrs);
		TypedArray tdarr = context.obtainStyledAttributes(attrs, R.styleable.McToggleButton);
		initTargetBgView(tdarr);
		initToggledTextColor(tdarr);
		initBackgroundAndIcons(tdarr);
		initWorkAsNormalBtn(tdarr);
		tdarr.recycle();
	}
	
//	private void initTargetBgView(Context context, AttributeSet attrs) {
//		bgViewId = attrs.getAttributeResourceValue(CompUtils.NS_TBC, BG_VIEW_ID, 0);
//		if (bgViewId <= 0) {
//			TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.TbcToggleButton);
//			bgViewId = attrArray.getResourceId(R.styleable.TbcToggleButton_bg_view_id, 0);
//		}
//	}
	
	//*↑
	private void initTargetBgView(TypedArray tdarr) {
		bgViewId = tdarr.getInt(R.styleable.McToggleButton_bg_view_id, 0);
	}

//	private void initWorkAsNormalBtn(Context context, AttributeSet attrs) {
//		workAsNormal = attrs.getAttributeBooleanValue(CompUtils.NS_TBC, AS_N_BTN, false);
//		if (!workAsNormal) {
//			TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.TbcToggleButton);
//			workAsNormal = attrArray.getBoolean(R.styleable.TbcToggleButton_work_as_normal_button, false);
//		}
//	}
	
	//*↑
	private void initWorkAsNormalBtn(TypedArray tdarr) {
		if (!workAsNormal) {
			workAsNormal = tdarr.getBoolean(R.styleable.McToggleButton_work_as_normal_button, false);
		}
	}

//	private void initToggledTextColor(Context context, AttributeSet attrs) {
//		this.normalTextColor = getCurrentTextColor();
//		int toggledTextColorId = attrs.getAttributeResourceValue(CompUtils.NS_TBC, T_COLOR, 0);
//		if (toggledTextColorId <= 0) {
//			TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.TbcToggleButton);
//			toggledTextColorId = attrArray.getResourceId(R.styleable.TbcToggleButton_toggled_text_color, 0);
//		}
//
//		if (toggledTextColorId > 0) {
//			toggledTextColor = getResources().getColor(toggledTextColorId);
//		} else {
//			toggledTextColor = normalTextColor;
//		}
//	}
	
	private void initToggledTextColor(TypedArray tdarr) {
		this.normalTextColor = getCurrentTextColor();
		toggledTextColor = tdarr.getColor(R.styleable.McToggleButton_toggled_text_color, 0);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		return touchProcessor(event);
	}

	private boolean touchProcessor(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			updatePressedView(true);
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			if (isCancleClick(event)) {
				updatePressedView(false);
				break;
			}

			if (workAsNormal) {
				updatePressedView(false);
				doAction(false);
			} else {
				updateToggleState();
			}

		}

		return true;
	}

	private void updateToggleState() {
		if (toggled == true) {
			if (buttonGroup == null || !buttonGroup.hasOthers(this)) {
				updateToggleView();
				doAction(true);
			} else {
				updatePressedView(false);
			}
		} else {
			updateToggleView();
			doAction(true);
		}
	}

	public boolean isCancleClick(MotionEvent event) {
		try {
			return event.getX() < 0 || event.getX() > bgView.getWidth() || event.getY() < 0 || event.getY() > bgView.getHeight();
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
	}

//	private void initBackgroundAndIcons(Context context, AttributeSet attrs) {
//
//		TypedArray attrArray = context.obtainStyledAttributes(attrs, R.styleable.TbcToggleButton);
//
//		toggledBg = getDrawable(attrs, attrArray, T_BG, R.styleable.TbcToggleButton_toggled_backgournd, null);
//		normalBgPressed = getDrawable(attrs, attrArray, N_BG_P, R.styleable.TbcToggleButton_noremal_backgournd_pressed, toggledBg);
//		toggledBgPressed = getDrawable(attrs, attrArray, T_BG_P, R.styleable.TbcToggleButton_toggled_backgournd_pressed, normalBg);
//
//		this.normalIcons = getCompoundDrawables();
//		this.toggledIcons = new Drawable[4];
//
//		toggledIcons[0] = getDrawable(attrs, attrArray, T_ICONS[0], R.styleable.TbcToggleButton_toggled_icon_left, normalIcons[0]);
//		toggledIcons[1] = getDrawable(attrs, attrArray, T_ICONS[1], R.styleable.TbcToggleButton_toggled_icon_top, normalIcons[1]);
//		toggledIcons[2] = getDrawable(attrs, attrArray, T_ICONS[2], R.styleable.TbcToggleButton_toggled_icon_right, normalIcons[2]);
//		toggledIcons[3] = getDrawable(attrs, attrArray, T_ICONS[3], R.styleable.TbcToggleButton_toggled_icon_bottom, normalIcons[3]);
//	}
	
	//*↑
	private void initBackgroundAndIcons(TypedArray tdarr) {
		toggledBg = tdarr.getDrawable(R.styleable.McToggleButton_toggled_backgournd);
		normalBgPressed = tdarr.getDrawable(R.styleable.McToggleButton_noremal_backgournd_pressed);
		toggledBgPressed = tdarr.getDrawable(R.styleable.McToggleButton_toggled_backgournd_pressed);

		this.normalIcons = getCompoundDrawables();
		this.toggledIcons = new Drawable[4];

		toggledIcons[0] = tdarr.getDrawable(R.styleable.McToggleButton_toggled_icon_left);
		toggledIcons[1] = tdarr.getDrawable(R.styleable.McToggleButton_toggled_icon_top);
		toggledIcons[2] = tdarr.getDrawable(R.styleable.McToggleButton_toggled_icon_right);
		toggledIcons[3] = tdarr.getDrawable(R.styleable.McToggleButton_toggled_icon_bottom);
	}

//	private Drawable getDrawable(AttributeSet attrs, TypedArray attrArray, String attrName, int styleId, Drawable defValue) {
//		int resourceId = attrs.getAttributeResourceValue(CompUtils.NS_TBC, attrName, 0);
//		if (resourceId <= 0) {
//			resourceId = attrArray.getResourceId(styleId, 0);
//		}
//
//		if (resourceId <= 0) {
//			return defValue;
//		}
//
//		Resources resources = getResources();
//		return resources.getDrawable(resourceId);
//	}
	

	public void toggle(boolean toggle, boolean notifyGroup) {
		if (this.toggled == toggle) {
			return;
		}

		initBgView();

		updateToggleView();
		doAction(notifyGroup);
	}

	private void doAction(boolean notifyGroup) {
		if (this.listener != null) {
			listener.onClick(this);
		}

		if (notifyGroup && !workAsNormal && this.buttonGroup != null) {
			buttonGroup.notityToggled(this);
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		initBgView();
		super.onDraw(canvas);
	}

	public void updateToggleView() {
		try {
			if (toggled) {
				bgView.setBackgroundDrawable(normalBg);
				setCompoundDrawablesWithIntrinsicBounds(normalIcons[0], normalIcons[1], normalIcons[2], normalIcons[3]);
				setTextColor(normalTextColor);
				toggled = false;
			} else {
				bgView.setBackgroundDrawable(toggledBg);
				setCompoundDrawablesWithIntrinsicBounds(toggledIcons[0], toggledIcons[1], toggledIcons[2], toggledIcons[3]);
				setTextColor(toggledTextColor);
				toggled = true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void updatePressedView(boolean pressed) {
		try {
			if (!toggled) {
				if (pressed == false) {
					bgView.setBackgroundDrawable(normalBg);
				} else {
					bgView.setBackgroundDrawable(normalBgPressed);
				}
			} else {
				if (pressed == false) {
					bgView.setBackgroundDrawable(toggledBg);
				} else {
					bgView.setBackgroundDrawable(toggledBgPressed);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void initBgView() {
		try {
			if (bgView != null) {
				return;
			}

			if (bgViewId == 0) {
				bgView = this;
			} else {
				bgView = findTargetViewById(this, bgViewId);
				if (bgView == null) {
					bgView = this;
				}
			}

			this.normalBg = bgView.getBackground();
			if (toggledBg == null) {
				toggledBg = normalBg;
			}

			if (toggledBgPressed == null) {
				toggledBgPressed = normalBg;
			}

			if (normalBgPressed == null) {
				normalBgPressed = toggledBg;
			}

			if (!this.equals(bgView)) {
				bgView.setOnTouchListener(new OnTouchListener() {

					@Override
					public boolean onTouch(View v, MotionEvent event) {
						return touchProcessor(event);
					}
				});
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public boolean isToggled() {
		return toggled;
	}

	public void setToggled(boolean toggled) {
		this.toggled = toggled;
	}

	@Override
	public void setOnClickListener(OnClickListener l) {
		this.listener = l;
	}

	@Override
	public void setClickable(boolean clickable) {
		super.setClickable(false);
	}

	public Drawable getNormalBg() {
		return normalBg;
	}

	public void setNormalBg(Drawable normalBg) {
		this.normalBg = normalBg;
	}

	public Drawable getNormalBgPressed() {
		return normalBgPressed;
	}

	public void setNormalBgPressed(Drawable normalBgPressed) {
		this.normalBgPressed = normalBgPressed;
	}

	public Drawable[] getNormalIcons() {
		return normalIcons;
	}

	public void setNormalIcons(Drawable[] normalIcons) {
		this.normalIcons = normalIcons;
	}

	public int getNormalTextColor() {
		return normalTextColor;
	}

	public void setNormalTextColor(int normalTextColor) {
		this.normalTextColor = normalTextColor;
	}

	public Drawable getToggledBg() {
		return toggledBg;
	}

	public void setToggledBg(Drawable toggledBg) {
		this.toggledBg = toggledBg;
	}

	public Drawable getToggledBgPressed() {
		return toggledBgPressed;
	}

	public void setToggledBgPressed(Drawable toggledBgPressed) {
		this.toggledBgPressed = toggledBgPressed;
	}

	public Drawable[] getToggledIcons() {
		return toggledIcons;
	}

	public void setToggledIcons(Drawable[] toggledIcons) {
		this.toggledIcons = toggledIcons;
	}

	public int getToggledTextColor() {
		return toggledTextColor;
	}

	public void setToggledTextColor(int toggledTextColor) {
		this.toggledTextColor = toggledTextColor;
	}

	public OnClickListener getListener() {
		return listener;
	}

	public void setListener(OnClickListener listener) {
		this.listener = listener;
	}

	public ButtonGroup getButtonGroup() {
		return buttonGroup;
	}

	public void setButtonGroup(ButtonGroup buttonGroup) {
		if (this.buttonGroup != null) {
			this.buttonGroup.remove(this);
		}

		this.buttonGroup = buttonGroup;

		if (this.buttonGroup != null) {
			this.buttonGroup.add(this);
		}
	}

	public static class ButtonGroup {

		private Set<McToggleButton> togleBtns;

		public ButtonGroup() {
			super();
			togleBtns = new HashSet<McToggleButton>(5);
		}

		void add(McToggleButton toggleButton) {
			togleBtns.add(toggleButton);
		}

		void remove(McToggleButton mcToggleButton) {
			togleBtns.remove(mcToggleButton);
		}

		void notityToggled(McToggleButton toggledButton) {
			for (McToggleButton btn : togleBtns) {
				if (!btn.equals(toggledButton)) {
					btn.toggle(false, false);
				}
			}
		}

		void clear() {
			togleBtns.clear();
		}

		int size() {
			return togleBtns.size();
		}

		boolean hasOthers(McToggleButton mcToggleButton) {

			return togleBtns.contains(mcToggleButton) && togleBtns.size() > 1;
		}
	}

	View findTargetViewById(View view, int targetId) {
		int id = view.getId();
		if (targetId == id) {
			return view;
		}

		ViewParent parent = view.getParent();
		if (parent == null) {
			return null;
		}

		if (!(parent instanceof View)) {
			return null;
		}

		View parentView = (View) parent;

		View targetView = parentView.findViewById(targetId);
		if (targetView != null) {
			return targetView;
		}

		return findTargetViewById(parentView, targetId);
	}
}
